<script>
    import { createEventDispatcher } from "svelte";
    import ApiClient from "@/utils/ApiClient";
    import CommonHelper from "@/utils/CommonHelper";
    import SortHeader from "@/components/base/SortHeader.svelte";
    import FormattedDate from "@/components/base/FormattedDate.svelte";
    import Scroller from "@/components/base/Scroller.svelte";

    const dispatch = createEventDispatcher();
    const labelMethodClass = {
        get: "label-info",
        post: "label-success",
        patch: "label-warning",
        delete: "label-danger",
    };

    export let filter = "";
    export let presets = "";
    export let sort = "-rowid";

    let items = [];
    let currentPage = 1;
    let totalItems = 0;
    let isLoading = false;
    let yieldedItemsId = 0;

    $: if (typeof sort !== "undefined" || typeof filter !== "undefined" || typeof presets !== "undefined") {
        clearList();
        load(1);
    }

    $: canLoadMore = totalItems > items.length;

    export async function load(page = 1, breakTasks = true) {
        isLoading = true;

        return ApiClient.logs
            .getRequestsList(page, 30, {
                sort: sort,
                filter: [presets, filter].filter(Boolean).join("&&"),
            })
            .then(async (result) => {
                if (page <= 1) {
                    clearList();
                }

                isLoading = false;
                currentPage = result.page;
                totalItems = result.totalItems;
                dispatch("load", items.concat(result.items));

                // optimize the items listing by rendering the rows in task batches
                if (breakTasks) {
                    const currentYieldId = ++yieldedItemsId;
                    while (result.items.length) {
                        if (yieldedItemsId != currentYieldId) {
                            break; // new yeild has been started
                        }

                        items = items.concat(result.items.splice(0, 10));

                        await CommonHelper.yieldToMain();
                    }
                } else {
                    items = items.concat(result.items);
                }
            })
            .catch((err) => {
                if (!err?.isAbort) {
                    isLoading = false;
                    console.warn(err);
                    clearList();
                    ApiClient.error(err, err?.status != 400); // silence filter errors
                }
            });
    }

    function clearList() {
        items = [];
        currentPage = 1;
        totalItems = 0;
    }
</script>

<Scroller class="table-wrapper">
    <table class="table" class:table-loading={isLoading}>
        <thead>
            <tr>
                <SortHeader disable class="col-field-method" name="method" bind:sort>
                    <div class="col-header-content">
                        <i class="ri-global-line" />
                        <span class="txt">Method</span>
                    </div>
                </SortHeader>

                <SortHeader disable class="col-type-text col-field-url" name="url" bind:sort>
                    <div class="col-header-content">
                        <i class={CommonHelper.getFieldTypeIcon("url")} />
                        <span class="txt">URL</span>
                    </div>
                </SortHeader>

                <SortHeader disable class="col-type-text col-field-referer" name="referer" bind:sort>
                    <div class="col-header-content">
                        <i class={CommonHelper.getFieldTypeIcon("url")} />
                        <span class="txt">Referer</span>
                    </div>
                </SortHeader>

                <SortHeader disable class="col-type-number col-field-userIp" name="userIp" bind:sort>
                    <div class="col-header-content">
                        <i class={CommonHelper.getFieldTypeIcon("number")} />
                        <span class="txt">User IP</span>
                    </div>
                </SortHeader>

                <SortHeader disable class="col-type-number col-field-status" name="status" bind:sort>
                    <div class="col-header-content">
                        <i class={CommonHelper.getFieldTypeIcon("number")} />
                        <span class="txt">Status</span>
                    </div>
                </SortHeader>

                <SortHeader disable class="col-type-date col-field-created" name="created" bind:sort>
                    <div class="col-header-content">
                        <i class={CommonHelper.getFieldTypeIcon("date")} />
                        <span class="txt">Created</span>
                    </div>
                </SortHeader>

                <th class="col-type-action min-width" />
            </tr>
        </thead>
        <tbody>
            {#each items as item (item.id)}
                <tr
                    tabindex="0"
                    class="row-handle"
                    on:click={() => dispatch("select", item)}
                    on:keydown={(e) => {
                        if (e.code === "Enter") {
                            e.preventDefault();
                            dispatch("select", item);
                        }
                    }}
                >
                    <td class="col-type-text col-field-method min-width">
                        <span class="label txt-uppercase {labelMethodClass[item.method.toLowerCase()]}">
                            {item.method?.toUpperCase()}
                        </span>
                    </td>

                    <td class="col-type-text col-field-url">
                        <span class="txt txt-ellipsis" title={item.url}>
                            {item.url}
                        </span>
                        {#if item.meta?.errorMessage || item.meta?.errorData}
                            <i class="ri-error-warning-line txt-danger m-l-5 m-r-5" title="Error" />
                        {/if}
                    </td>

                    <td class="col-type-text col-field-referer">
                        <span class="txt txt-ellipsis" class:txt-hint={!item.referer} title={item.referer}>
                            {item.referer || "N/A"}
                        </span>
                    </td>

                    <td class="col-type-number col-field-userIp">
                        <span class="txt txt-ellipsis" class:txt-hint={!item.userIp} title={item.userIp}>
                            {item.userIp || "N/A"}
                        </span>
                    </td>

                    <td class="col-type-number col-field-status">
                        <span class="label" class:label-danger={item.status >= 400}>
                            {item.status}
                        </span>
                    </td>

                    <td class="col-type-date col-field-created">
                        <FormattedDate date={item.created} />
                    </td>

                    <td class="col-type-action min-width">
                        <i class="ri-arrow-right-line" />
                    </td>
                </tr>
            {:else}
                {#if isLoading}
                    <tr>
                        <td colspan="99" class="p-xs">
                            <span class="skeleton-loader m-0" />
                        </td>
                    </tr>
                {:else}
                    <tr>
                        <td colspan="99" class="txt-center txt-hint p-xs">
                            <h6>No logs found.</h6>
                            {#if filter?.length}
                                <button
                                    type="button"
                                    class="btn btn-hint btn-expanded m-t-sm"
                                    on:click={() => (filter = "")}
                                >
                                    <span class="txt">清除</span>
                                </button>
                            {/if}
                        </td>
                    </tr>
                {/if}
            {/each}
        </tbody>
    </table>
</Scroller>

{#if items.length}
    <small class="block txt-hint txt-right m-t-sm">Showing {items.length} of {totalItems}</small>
{/if}

{#if items.length && canLoadMore}
    <div class="block txt-center m-t-xs">
        <button
            type="button"
            class="btn btn-lg btn-secondary btn-expanded"
            class:btn-loading={isLoading}
            class:btn-disabled={isLoading}
            on:click={() => load(currentPage + 1)}
        >
            <span class="txt">Load more ({totalItems - items.length})</span>
        </button>
    </div>
{/if}
